// COMTRADE 解析 TypeScript 优化版（支持 BINARY 格式二进制解析）
// 存储为 _v1_20250530 版本
// 仅实现 cfg/dat 文件解析与数据结构，便于后续绘图等扩展

/**
 * 模拟 C++ 的 ComtradeAnalogChannel，模拟量通道定义
 */
export interface ComtradeAnalogChannel {
  index: number;
  id: string;
  phase: string;
  ccbm: string;
  unit: string;
  multiplier: number;
  offset: number;
  channelSkewus: number;
  minValue: number;
  maxValue: number;
  primaryRatio: number;
  secondaryRatio: number;
  scaling: "p" | "s";
}

/**
 * 开关量通道定义
 */
export interface ComtradeDigitalChannel {
  index: number;
  id: string;
  phase: string;
  ccbm: string;
  normalState: boolean;
}

/**
 * COMTRADE 主数据结构
 */
export interface ComtradeRecord {
  analogChannels: ComtradeAnalogChannel[];
  digitalChannels: ComtradeDigitalChannel[];
  sampleRates: number[];
  lastSamples: number[];
  timeMultiplier: number;
  triggerOffsetms: number;
}

/**
 * 解析 cfg 文件，生成 ComtradeRecord
 * @param cfgContent cfg 文件内容
 */
export function parseComtradeCfg(cfgContent: string): ComtradeRecord {
  const lines = cfgContent.split(/\r?\n/).filter((l) => l.trim().length > 0);
  let idx = 0;
  idx++;
  const [totalChannelsStr, analogStr, digitalStr] = lines[idx++].split(",");
  const totalChannels = parseInt(totalChannelsStr);
  const analogChannels = parseInt(analogStr.slice(0, -1));
  const digitalChannels = parseInt(digitalStr.slice(0, -1));
  if (totalChannels !== analogChannels + digitalChannels) throw new Error("通道数不匹配");
  const analogs: ComtradeAnalogChannel[] = [];
  for (let i = 0; i < analogChannels; ++i) {
    analogs.push(parseAnalogChannel(lines[idx++]));
  }
  const digitals: ComtradeDigitalChannel[] = [];
  for (let i = 0; i < digitalChannels; ++i) {
    digitals.push(parseDigitalChannel(lines[idx++]));
  }
  idx++;
  const nRates = parseInt(lines[idx++]);
  const sampleRates: number[] = [];
  const lastSamples: number[] = [];
  for (let i = 0; i < nRates; ++i) {
    const [rate, lastSample] = lines[idx++].split(",");
    sampleRates.push(parseFloat(rate));
    lastSamples.push(parseInt(lastSample));
  }
  idx += 2;
  if (lines[idx++].trim().toUpperCase() !== "BINARY") throw new Error("仅支持 BINARY 格式");
  const timeMultiplier = parseFloat(lines[idx++]);
  let triggerOffsetms = 0;
  if (lines[idx]) {
    const offset = parseFloat(lines[idx]);
    if (!isNaN(offset)) triggerOffsetms = offset;
  }
  return {
    analogChannels: analogs,
    digitalChannels: digitals,
    sampleRates,
    lastSamples,
    timeMultiplier,
    triggerOffsetms,
  };
}

function parseAnalogChannel(line: string): ComtradeAnalogChannel {
  const tokens = line.trim().split(",");
  if (tokens.length !== 13) throw new Error("Analog channel cfg 行格式错误: " + line);
  return {
    index: parseInt(tokens[0]),
    id: tokens[1],
    phase: tokens[2],
    ccbm: tokens[3],
    unit: tokens[4],
    multiplier: parseFloat(tokens[5]),
    offset: parseFloat(tokens[6]),
    channelSkewus: parseFloat(tokens[7]),
    minValue: parseInt(tokens[8]),
    maxValue: parseInt(tokens[9]),
    primaryRatio: parseFloat(tokens[10]),
    secondaryRatio: parseFloat(tokens[11]),
    scaling: tokens[12].toLowerCase() === "p" ? "p" : "s",
  };
}

function parseDigitalChannel(line: string): ComtradeDigitalChannel {
  const tokens = line.trim().split(",");
  if (tokens.length !== 5) throw new Error("Digital channel cfg 行格式错误: " + line);
  return {
    index: parseInt(tokens[0]),
    id: tokens[1],
    phase: tokens[2],
    ccbm: tokens[3],
    normalState: Boolean(parseInt(tokens[4])),
  };
}

/**
 * 读取 BINARY 格式 dat 文件，返回采样数据
 * @param datBuffer dat 文件内容（二进制 ArrayBuffer）
 * @param record ComtradeRecord
 * @param options 可选参数：每个采样点字节数、字节序等
 */
export function loadComtradeSamples(
  datBuffer: ArrayBuffer,
  record: ComtradeRecord,
  options?: {
    sampleSize?: number; // 每个采样点字节数，默认2（16位）
    littleEndian?: boolean; // 字节序，默认true
  }
): {
  analogSamples: number[][];
  digitalSamples: number[][];
  timeBaseus: number[];
} {
  const totalSamples = record.lastSamples[record.lastSamples.length - 1];
  const analogCount = record.analogChannels.length;
  const digitalCount = record.digitalChannels.length;
  const sampleSize = options?.sampleSize ?? 2; // 默认16位short
  const littleEndian = options?.littleEndian ?? true;
  // 每条数据 = 采样序号 + 时间戳 + N个模拟量 + N个开关量
  // 假设标准格式：采样序号(int32) + 时间戳(int32) + analogs(int16*N) + digitals(uint16*ceil(D/16))
  const analogBytes = analogCount * sampleSize;
  const digitalWords = Math.ceil(digitalCount / 16); // 每16个数字量占2字节
  const digitalBytes = digitalWords * 2;
  const rowBytes = 4 + 4 + analogBytes + digitalBytes; // 采样序号+时间戳+模拟量+开关量
  const dv = new DataView(datBuffer);
  const analogSamples: number[][] = Array.from({ length: analogCount }, () =>
    Array(totalSamples).fill(0)
  );
  const digitalSamples: number[][] = Array.from({ length: digitalCount }, () =>
    Array(totalSamples).fill(0)
  );
  const timeBaseus: number[] = Array(totalSamples).fill(0);
  let offset = 0;
  for (let i = 0; i < totalSamples; ++i) {
    if (offset + rowBytes > datBuffer.byteLength) break;
    // 采样序号
    /* const sampleIdx = */ dv.getInt32(offset, littleEndian);
    offset += 4;
    // 时间戳
    const timeRaw = dv.getInt32(offset, littleEndian);
    offset += 4;
    timeBaseus[i] = timeRaw * record.timeMultiplier;
    // 模拟量
    for (let j = 0; j < analogCount; ++j) {
      const raw = dv.getInt16(offset, littleEndian);
      offset += sampleSize;
      const ch = record.analogChannels[j];
      analogSamples[j][i] = ch.multiplier * raw + ch.offset;
    }
    // 开关量
    for (let w = 0; w < digitalWords; ++w) {
      const word = dv.getUint16(offset, littleEndian);
      offset += 2;
      for (let b = 0; b < 16; ++b) {
        const idx = w * 16 + b;
        if (idx < digitalCount) {
          digitalSamples[idx][i] = word & (1 << b) ? 1 : 0;
        }
      }
    }
  }
  return { analogSamples, digitalSamples, timeBaseus };
}

// 用法示例：
// const record = parseComtradeCfg(cfgText);
// const { analogSamples, digitalSamples, timeBaseus } = loadComtradeSamples_v1_20250530(arrayBuffer, record);
